package org.myhibernate.core;
import java.sql.Connection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.myhibernate.Method;
import org.myhibernate.cache.CacheItem;
import org.myhibernate.cache.RemoveSqlCaches;
import org.myhibernate.db.DataHelper;
/**
 * 
 * @author liujun
 *
 * @param <T>
 */
public class Template<T>
{
	private Connection connection=null;
	private Method<T> method=null;
	private Class<T> cls=null;
	private DataHelper helper=new DataHelper();
	private Map<String, String> methodMap=Mappings.getMethodMap();
	public Template(Class<T> cls) {
		this.cls=cls;
	}
	public Template(Class<T> cls,Connection conn) {
		this.cls=cls;
		this.connection=conn;
	}
	public boolean save(T t) throws Exception
	{
		boolean flag=false;
		try {
			method=getMethod(methodMap.get("add"));
			method.init(cls, getConnection(), helper);
			method.execute(t,null);
			flag=true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.toString());
		}
		return flag;
	}
	public boolean save(List<T> list) throws Exception
	{
		boolean flag=false;
		try {
			method=getMethod(methodMap.get("addbatch"));
			method.init(cls, getConnection(), helper);
			method.execute(list,null);
			flag=true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.toString());
		}
		return flag;
	}
	public boolean delete(Object id) throws Exception
	{
		boolean flag=false;
		try {
			method=getMethod(methodMap.get("delete"));
			method.init(cls, getConnection(), helper);
			flag=Boolean.parseBoolean(method.execute(id,null)+"");
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.toString());
		}
		return flag;
	}
	public boolean deletes(List<Object> idList) throws Exception
	{
		boolean flag=false;
		try {
			method=getMethod(methodMap.get("deletes"));
			method.init(cls, getConnection(), helper);
			flag=Boolean.parseBoolean(method.execute(idList,null)+"");
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.toString());
		}
		return flag;
	}
	public boolean update(T t) throws Exception
	{
		boolean flag=false;
		
		try {
			method=getMethod(methodMap.get("update"));
			method.init(cls, getConnection(), helper);
			method.execute(t,null);
			flag=true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.toString());
		}
		return flag;
	}
	public boolean update(T t,String[] fieldNames) throws Exception
	{
		if ((fieldNames ==null)||(fieldNames.length == 0))
		{
			return true;
		}
		Map<String, Object> map=new HashMap<String, Object>();
		map.put("fieldNames", fieldNames);
		boolean flag=false;
		try {
			method=getMethod(methodMap.get("updatefield"));
			method.init(cls, getConnection(), helper);
			method.execute(t,map);
			flag=true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.toString());
		}
		
		return flag;
	}
	public boolean update(List<T> list) throws Exception
	{
		boolean flag=false;
		
		try {
			method=getMethod(methodMap.get("updatebatch"));
			method.init(cls, getConnection(), helper);
			method.execute(list,null);
			flag=true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.toString());
		}
		return flag;
	}
	
	/***
	 * get a object from cache
	 * @param id
	 * @return
	 * @throws RuntimeException
	 */
	public T get(Object id) throws Exception
	{
		Object t=null;
		try {
			method=getMethod(methodMap.get("get"));
			method.init(cls, getConnection(), helper);
			t=method.execute(id,null);
			if (t==null) 
			{
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.toString());
		}
		return (T) t;
	}
	
	/***
	 * load a object direct from database
	 * @param id
	 * @return
	 * @throws RuntimeException
	 */
	public T load(Object id) throws Exception
	{
		Object t=null;
		try {
			method=getMethod(methodMap.get("load"));
			method.init(cls, getConnection(), helper);
			t=method.execute(id,null);
			if (t==null) 
			{
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.toString());
		}
		return (T) t;
	}
	public CacheItem getItem(Object id) throws Exception
	{ 
		CacheItem item=null;
		try {
			method=getMethod(methodMap.get("getitem"));
			method.init(cls, getConnection(), helper);
			item=(CacheItem) method.execute(id,null);
			if (item==null) 
			{
				return null;
			}
		} catch (Exception e) {
			throw new RuntimeException(e.toString());
		}
		return item;
	}
	public Method<T> getPageSizeQuery()
	{
		method=getMethod(methodMap.get("pagesizequery"));
		method.init(cls, getConnection(), helper);
		return method;
	}
	
	public Connection getConnection() {
		return connection;
	}
	public DataHelper getHelper() {
		return helper;
	}
	private Method<T> getMethod(String className) 
	{
		try {
			Method method=(Method) Class.forName(className).newInstance();
			return method;
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	public void clear()
	{
		new RemoveSqlCaches(cls);
	}
	public void close()
	{
		try {
			if (connection!=null) {
				connection.close();
				connection=null;
			}
		} catch (Exception e) {
		}
		if (method!=null) {
			method.close();
		}
		if (helper!=null) {
			helper.close();
		}
	}
	
}
